在ubuntu上已经安装了vivado和vitis的环境后,就可以通过ubuntu系统上的vitis开发应用程序。和在windows上一样,需要先创建平台工程,再创建相应的应用工程。
在我们创建petalinux工程时已经将xsa文件导入到了ubuntu里,此时选择此xsa文件,并将系统选择为Linux系统:点击finish
创建应用工程,本次我们只创建一个应用工程,将不同的外设测试分模块进行,首先创建一个应用工程:
点击finish,应用工程建立完成。
目前的GPIO配置中使能了2个MIO LED/2个EMIO LED,2个MIO KEY/2个EMIO KEY,以及一个蜂鸣器。
在Linux系统中,可以通过sysfs接口方便地控制GPIO。下面介绍如何在Zynq-7020平台上使用sysfs控制GPIO。
Zynq-7020的GPIO分为:
MIO (Multiplexed I/O): 直接连接到PS(处理系统)的54个引脚
EMIO (Extended MIO): 通过PL(可编程逻辑)扩展的GPIO
首先需要确定你要控制的GPIO在Linux系统中的编号。/sys/class/gpio下的gpiochips编号对应第一个GPIO及MIO0的编号,一般是906。
# 查看gpio的设备名称cd /sys/class/gpiols# ls展示的结果:export gpiochip906 unexport# 说明gpio的设备名称为gpiochip906,对应的起始序号是906# MIO有54个,所以EMIO从906+54=960开始GPIO编号计算公式:
MIO GPIO: MIO的原始编号为053,对应的在linux下的编号为906959
EMIO GPIO: EMIO的编号从54开始,对应在linux下的编号为960开始
例如:
MIO11对应GPIO编号917
EMIO GPIO0对应GPIO编号960
假设要控制EMIO0,则需要先将该GPIO导出
xxxxxxxxxx# 导出GPIO54echo 960 > /sys/class/gpio/export设置GPIO为输出或输入模式:
x# 设置为输出模式echo out > /sys/class/gpio/gpio960/direction# 或者设置为输入模式echo in > /sys/class/gpio/gpio960/direction# 查询引脚方向cat /sys/class/gpio/gpio960/direction
输出模式(控制LED等):
xxxxxxxxxx# 输出高电平echo 1 > /sys/class/gpio/gpio960/value# 输出低电平echo 0 > /sys/class/gpio/gpio960/value
输入模式(读取按键等):
xxxxxxxxxx# 读取GPIO值cat /sys/class/gpio/gpio960/value
使用完毕后,可以取消导出:
xxxxxxxxxxecho 960 > /sys/class/gpio/unexport
右击"src"->"new"->"Foder"建立GPIO,TEST文件夹:
右击"GPIO"->"new"->"File"建立对应的.c/.h文件;右击"TEST"->"new"->"File"建立对应的.c文件;右击"src"->"new"->"File"建立main.c/main.h。
添加相应的代码后,最后的工程结构如下:
打开vitis,点击如下图标:
选择Linux Agent为default,并双击以配置该Agent:
弹出的界面中,Host的地方填入开发板的IP地址,端口保持默认值,不用改:
填完成后可以点击Test Connection以测试连接成功还是失败,出现下面内容则说明已经连接成功:
点击ok退出即可。
因为这块默认下载路径是SD卡的第一个分区,而默认第一个分区用来存放内核镜像、BOOT.BIN等信息。所以在/home/root下新建一个文件夹app,将编译生成的.elf文件下载到该文件夹下。
可以直接点击左上方的此图标进行代码的编译,也可以像之前一样点击“build project"进行编译:
如果出现此类错误
对应的解决办法是将头文件的路径添加到搜索路径中。
右击工程,选择"C/C++ Build Settings":
"Add"后:
加完之后页面:
此时就可以编译成功了。
Debug时,vitis会将代码下载到开发板的/home/root/app下运行。这时就可以通过vitis进行单步调试或断点调试。
xxxxxxxxxx// export GPIOvoid export_gpio(int pin) { char buffer[4]; int fd = open("/sys/class/gpio/export", O_WRONLY); if (fd < 0) { perror("Failed to open export"); exit(1); } snprintf(buffer, sizeof(buffer), "%d", pin); write(fd, buffer, strlen(buffer)); close(fd); usleep(100000); // wait sysfs node build}
// set GPIO directionvoid set_direction(int pin, const char* direction) { char path[64]; snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/direction", pin); int fd = open(path, O_WRONLY); if (fd < 0) { perror("Failed to open direction"); exit(1); } write(fd, direction, strlen(direction)); close(fd);}
// write GPIOvoid write_gpio(int pin, int value) { char path[64]; char val = value ? '1' : '0'; snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", pin); int fd = open(path, O_WRONLY); if (fd < 0) { perror("Failed to open value for writing"); exit(1); } write(fd, &val, 1); close(fd);}
// read GPIOint read_gpio(int pin) { char path[64]; char val; snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", pin); int fd = open(path, O_RDONLY); if (fd < 0) { perror("Failed to open value for reading"); exit(1); } read(fd, &val, 1); close(fd); return (val == '1') ? 1 : 0;}